package ntd.util.frame.task.handle;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.db.Entity;
import cn.hutool.log.StaticLog;
import com.ToolOpt;
import com.modular.system.task.opt.OptSysTaskCom;
import ntd.task.TaskManager;
import ntd.task.bo.TaskInfo;
import com.modular.system.task.bean.TaskDo;
import ntd.util.util.ToolDuration;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TaskManagerService {

    private static final Map<String, TaskDo> taskMap = new HashMap<>();
    private static OptSysTaskCom optSTask = ToolOpt.OPT_S_TASK;

    public static void executeTask() {
        ToolDuration.duration(() -> {
            // 查询所有任务
            List<TaskDo> taskDoList = optSTask.query().ne("status", "3").listBean();
            taskDoList.forEach(TaskManagerService::initTaskItem);
        }, "定时任务更新");
    }

    public static void initTaskItem(TaskDo taskDo) {
        // 查找任务缓存
        TaskDo oldTaskDo = taskMap.get(taskDo.getId());
        // 如果不存在或者任务更新，则从新初始化任务
        if (ObjectUtil.isNull(oldTaskDo) || DateUtil.compare(taskDo.getUpdatedDate(), oldTaskDo.getUpdatedDate()) != 0) {
            // 清除旧任务
            CronUtil.remove(taskDo.getId());
            // 添加新任务
            appendTask(taskDo);
            // 更新缓存对象
            taskMap.put(taskDo.getId(), taskDo);

            StaticLog.info("定时任务[{}]更新完成！", taskDo.getName());
        }
    }

    public static void appendTask(TaskDo taskDo) {
        TaskInfo taskInfo = TaskManager.get(taskDo.getTaskCode());

        if (ObjectUtil.isNull(taskInfo)) {
            StaticLog.error("任务执行器-找不到可执行的任务{}", taskDo.getTaskCode());
            return;
        }

        CronUtil.schedule(taskDo.getId(), taskDo.getCron(), () -> {
            // 任务加锁（解决分布式任务多次触发问题）
            if (lockTask(taskDo.getId())) {
                try {
                    // 执行任务
                    taskInfo.getTask().execute(taskDo.getJsonParams());
                } catch (Throwable e) {
                    StaticLog.error(e, "[任务][执行][{}]失败...", taskDo.getId());
                } finally {
                    // 任务解锁
                    unLockTask(taskDo.getId());
                }
            }

        });
    }

    private static boolean lockTask(String taskId) {
        return optSTask.syncEntity(new Entity().set("status", 1), new Entity().set("id", taskId).set("status", 0)) == 1;
    }

    private static boolean unLockTask(String taskId) {
        return optSTask.syncEntity(new Entity().set("status", 0), new Entity().set("id", taskId).set("status", 1)) == 1;
    }

    public static void main(String[] args) {
        lockTask("402896817ffa3b45017ffa6f805d000c");
    }
}
